package com.kaifamiao.wendao.dao;

import com.kaifamiao.wendao.entity.Customer;
import org.apache.commons.dbutils.ResultSetHandler;

import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class CustomerDao extends BaseDao<Customer,Long> {

    private static final String SELECT_BASE = "SELECT id, username, password, salt, nickname, reg_date FROM t_customers";
    private static final String SELECT_ONE_BY_ID = SELECT_BASE + " WHERE id = ?";
    private static final String SELECT_ONE_BY_USERNAME = SELECT_BASE + " WHERE username = ?";
    private static final String SELECT_ALL = SELECT_BASE + " ORDER BY id";
    private static final String INSERT = "INSERT INTO t_customers (username, password, salt, nickname, reg_date, id) VALUES (?,?,?,?,?,?)";
    private static final String UPDATE = "UPDATE t_customers SET username=?, password=?, salt=?, nickname=? WHERE id =?";
    private static final String DELETE = "DELETE FROM t_customers WHERE id = ?";

    private ResultSetHandler<List<Customer>> listHandler = rs -> {
        List<Customer> customers = new ArrayList<>();
        while(rs.next()){
            Customer c = new Customer();
            c.setId(rs.getLong("id"));
            c.setUsername(rs.getString("username"));
            c.setPassword(rs.getString("password"));
            c.setSalt(rs.getString("salt"));
            c.setNickname(rs.getString("nickname"));
            java.sql.Date date = rs.getDate("reg_date");
            LocalDate regDate = date == null ? null : date.toLocalDate();
            c.setRegisterDate(regDate);
            customers.add(c);
        }
        return customers;
    };

    private ResultSetHandler<Customer> singleHandler = rs -> {
        Customer c = null;
        if(rs.next()){
            c = new Customer();
            c.setId(rs.getLong("id"));
            c.setUsername(rs.getString("username"));
            c.setPassword(rs.getString("password"));
            c.setSalt(rs.getString("salt"));
            c.setNickname(rs.getString("nickname"));
            java.sql.Date date = rs.getDate("reg_date");
            LocalDate regDate = date == null ? null : date.toLocalDate();
            c.setRegisterDate(regDate);
        }
        return c;
    };

    @Override
    public boolean save(Customer c) {
        try {
            LocalDate regDate = c.getRegisterDate();
            java.sql.Date date = regDate != null ? java.sql.Date.valueOf(regDate) : null ;
            int count = runner.update(INSERT, c.getUsername(),c.getPassword(),c.getSalt(),c.getNickname(),date,c.getId());
            return count == 1;
        }catch (SQLException cause){
            throw new RuntimeException("保存失败",cause);
        }
    }

    @Override
    public boolean update(Customer c) {
        try {
            int count = runner.update(UPDATE, c.getUsername(), c.getPassword(), c.getSalt(), c.getNickname(), c.getId());
            return count == 1;
        }catch (SQLException cause){
            throw new RuntimeException("更新失败",cause);
        }
    }

    @Override
    public boolean remove(Long id) {
        try {
            int count = runner.update(DELETE, id);
            return count == 1;
        }catch (SQLException cause){
            throw new RuntimeException("删除失败",cause);
        }
    }

    @Override
    public List<Customer> findAll() {
        try {
            return runner.query(SELECT_ALL, listHandler);
        }catch (SQLException cause){
            throw new RuntimeException("查询失败",cause);
        }
    }

    @Override
    public Customer find(Long id) {
        try {
            return runner.query(SELECT_ONE_BY_ID, singleHandler, id);
        }catch (SQLException cause){
            throw new RuntimeException("查询失败",cause);
        }
    }

    /**
     * 检查指定用户名在数据库表中是否已经存在
     * @param username 待检查用户名
     * @return 仅当用户名已经存在于数据库中时返回 true ；否则，返回 false 。
     */
    public boolean exists(String username) {
        try {
            // 执行查询语句，只要结果集中有数据返回即返回 true
            return runner.query(SELECT_ONE_BY_USERNAME, rs -> rs.next(), username);
        } catch (SQLException cause) {
            throw new RuntimeException("查询失败", cause);
        }
    }

    /**
     * 根据用户名查询单个用户
     * @param username 待查询用户名
     * @return 指定用户名对应的Customer对象
     */
    public Customer find(String username) {
        try {
            return runner.query(SELECT_ONE_BY_USERNAME, singleHandler, username);
        }catch (SQLException cause){
            throw new RuntimeException("查询失败",cause);
        }
    }

}
